#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mysql_resultset.h"

namespace sql
{


	ResultSet::ResultSet( ) : mMysqlResult( NULL ), mValue( NULL )
	{
		Free( );
	}

	ResultSet::~ResultSet( )
	{
		Free( );
	}

	void ResultSet::close( )
	{
		Free( );
	}

	void ResultSet::Free( )
	{
		if ( mMysqlResult != NULL )
		{
			mysql_free_result( mMysqlResult );
			mMysqlResult = NULL;
		}

		mRowCount = 0;
		mLowCount = 0;
		mCurRow = 0;
		mMysqlLowLength = NULL;

		freeValue( );
	}

	int ResultSet::Init( MYSQL* my_sql )
	{
		if ( my_sql == NULL ) return 0;
		mMysqlResult = mysql_store_result( my_sql );
		if ( mMysqlResult != NULL )
		{
			mRowCount = mysql_num_rows( mMysqlResult );
			mLowCount = mysql_num_fields( mMysqlResult );

			mCurRow = 0;

		}

		return 0;
	}

	bool ResultSet::IsUsing( )
	{
		return mMysqlResult != NULL;
	}

	bool ResultSet::next( )
	{
		if ( mMysqlResult == NULL ) return false;

		if ( ( mCurRow + 1 ) <= mRowCount )
		{
			mMysqlRow = mysql_fetch_row( mMysqlResult );
			if ( !mMysqlRow )
			{
				mMysqlLowLength = NULL;
				return false;
			}

			mCurRow++;

			mMysqlLowLength = mysql_fetch_lengths( mMysqlResult );

			return true;
		}

		return false;
	}

	const char* ResultSet::setValue( const char* value, uint32_t value_length )
	{
		if ( value_length > mValueLengthMax )
		{
			freeValue( );

			mValue = new char[ value_length + 4 ];
			if ( mValue != NULL )
			{
				memset( mValue, '\0', value_length + 4 );
				memcpy( mValue, value, value_length );
				mValueLengthMax = value_length;
				mValueLength = value_length;
			}
		}
		else
		{
			memset( mValue, '\0', mValueLength );
			memcpy( mValue, value, value_length );
			mValueLength = value_length;
		}

		return mValue;
	}

	void ResultSet::freeValue( )
	{
		if ( mValue != NULL )
		{
			delete[] mValue;
			mValue = NULL;
		}

		mValueLength = 0;
		mValueLengthMax = 0;
	}

	const char* ResultSet::GetValue( uint32_t columnIndex )
	{
		if ( mMysqlResult == NULL ) return NULL;
		if ( mMysqlLowLength == NULL ) return NULL;
		if ( mCurRow == 0 ) return NULL;
		if ( columnIndex <= 0 ) return NULL;
		if ( columnIndex > GetLowCount( ) ) return NULL;

		uint32_t find_low = columnIndex - 1;

		uint32_t length = mMysqlLowLength[ find_low ];

		if ( mMysqlRow )
		{
			return setValue( mMysqlRow[ find_low ], length );
		}

		return NULL;
	}

	const char* ResultSet::GetValue( const char* column_name )
	{
		return GetValue( findColumn( column_name ) );
	}

	uint32_t ResultSet::findColumn( const char* column_name )
	{
		for ( unsigned int i = 1; i <= GetLowCount( ); ++i )
		{
			MYSQL_FIELD* field = GetField( i );

			if ( field != NULL )
			{
				if ( strlen( column_name ) != strlen( field->name ) ) continue;

				if ( strncmp( column_name, field->name, strlen( column_name ) ) == 0 )
				{
					return i;
				}
			}
		}

		return 0;
	}

	int ResultSet::getInt( uint32_t columnIndex )
	{
		const char* value = GetValue( columnIndex );
		if ( value == NULL ) return 0;
		return atoi( value );
	}

	long long ResultSet::getInt64( uint32_t columnIndex )
	{
		const char* value = GetValue( columnIndex );
		if ( value == NULL ) return 0;
		return atoll( value );
	}

	long long ResultSet::getInt64( const char* name )
	{
		return getInt64( findColumn( name ) );
	}

	int ResultSet::getInt( const char* name )
	{
		return getInt( findColumn( name ) );
	}

	uint32_t ResultSet::getUInt( uint32_t columnIndex )
	{
		return ( uint32_t )getInt( columnIndex );
	}

	uint32_t ResultSet::getUint( const char* name )
	{
		return getUInt( findColumn( name ) );
	}

	const char* ResultSet::getStringStr( uint32_t columnIndex )
	{
		return GetValue( columnIndex );
	}

	const char* ResultSet::getStringStr( const char* name )
	{
		return GetValue( name );
	}

	std::string ResultSet::getString( uint32_t columnIndex )
	{
		const char* value = getStringStr( columnIndex );
		if ( value == NULL ) return "";
		return value;

	}

	std::string ResultSet::getString( const char* name )
	{
		const char* value = getStringStr( name );
		if ( value == NULL ) return "";
		return value;
	}

	const char*  ResultSet::getBlob( uint32_t columnIndex )
	{
		return GetValue( columnIndex );
	}

	const char* ResultSet::getBlob( const char* name )
	{
		return getBlob( findColumn( name ) );
	}

	const char* ResultSet::getFieldNameByCol( uint32_t column )
	{
		MYSQL_FIELD* field = GetField( column );
		if ( field == NULL ) return NULL;

		return field->name;
	}

	enum enum_field_types ResultSet::getColTypes( uint32_t column )
	{
		MYSQL_FIELD* field = GetField( column );
		if ( field == NULL ) return MYSQL_TYPE_DECIMAL;

		return field->type;
	}

	unsigned int ResultSet::getFieldLengthByCol( uint32_t column )
	{
		MYSQL_FIELD* field = GetField( column );
		if ( field == NULL ) return 0;

		return field->length;

	}

}



